home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
docs
/
mags
/
saku17.lha
/
Teksti
/
Ohjelmointi.txt
< prev
next >
Wrap
Text File
|
1996-03-01
|
27KB
|
659 lines
5
1*
{A Järjestelmäohjelmoinnin alkeiskurssi - Osa 4: GUI
{A -------------------------------------------------
{7 Sami Klemola
Alun perin tässä osassa, jonka olisi pitänyt tulla julkaistuksi jo hyvän
aikaa sitten, oli tarkoituksena käsitellä Intuitionia edelleen, mutta teemme
nyt hieman yllättävän käännöksen matkallamme kohti Amigan käyttöjärjestelmän
hallintaa. Käsittelemme kyllä edelliseen osaan jatkona menut ja gadgetit eli
valikot ja nappulat. Emme kuitenkaan tee niitä suoraan Intuitionin kanssa
kommunikoiden, vaan tutustumme GadToolsin päälle asettuvaan GUI-kirjastoon
nimeltä Triton.
GUI:n eli graafisen käyttöliittymän tekeminen helpottui sanottavasti Release
2:n myötä sen esiteltyä uuden gadtools.libraryn. Asiat ovat kuitenkin
edenneet vielä siitä, ja nyt uusinta uutta ovat kolmansien osapuolien
tuottamat oliopohjaiset kirjastot. Niistä ehkäpä tunnetuin on MUI, mutta se
on käyttökelvoton suunnattoman muistinkulutuksensa ja järjettömän hitautensa
takia.
Omaan käyttööni valitsin Tritonin, koska se on nopea ja pienikokoinen.
Lisäksi sitä on helppo ohjelmoida, ja sen kanssa graafisen käyttöliittymän
tekeminen on todella helppoa. Triton hoitaa kaikki yhteydet Intuitioniin ja
GadToolsiin sekä tarjoaa Intuitionin peruspalveluiden ja vielä GadToolsin
toimintojen lisäksi joukon omiaan. Kaikki nämä ovat Tritonin kanssa olioita,
joiden käsittely on erittäin yksinkertaista.
Oliot toimivat itsenäisesti Tritonin alaisuudessa, ja niiden kanssa voidaan
olla tekemisissä sen kautta. Niiden tilasta saadaan tietoja ja niiden tilaa
voi muuttaa. Kun käyttäjä aktivoi olion, Triton kertoo siitä ohjelmalle
lähettämällä viestin. Triton-ohjelman toiminta on viestien vastaanottamista
ja niiden pohjalta toimimista. Tritonin kanssa ohjelma voi keskittyä
olennaiseen, ja ohjelmoija voi tyystin unohtaa ongelmat erikokoisten
kirjasinten ja ikkunan koon muuttumisen kanssa.
Triton on osittain sharewarea. Itse kirjaston käyttämisestä ohjelmien
ajamiseen ja omien ohjelmien tekemiseen ei tarvitse maksaa mitään, mutta
Tritoniin kuuluu Prefs-editori, jolla voidaan asetella kunkin
Triton-ohjelman ikkunat sopiviksi, ja sen käytöstä pitää maksaa 15 dollarin
tai 20 Saksan markan suuruinen hinta. Rekisteröity versio pitää siis
muistissa ikkunoiden paikat, ja ohjelmien ikkunat aukeavat aina niin kuin
olet ne viimeksi asettanut!
Tämä artikkeli ei ole kattava opastus graafisen käyttöliittymän tekemiseen
Tritonilla. Itse asiassa tässä on vain pieniä tiedonpalasia sieltä täältä,
mutta kunnollista kokonaisuutta ei saa muodostettua ennen kuin tutustuu
lähemmin Tritonin omaan dokumentaatioon. Jossakin tulevassa osassa voimme
vielä palata Tritoniin esimerkiksi olioiden läpikäymisen merkeissä, mutta
toistaiseksi tietoa niistä on aika vähän. Käydään kuitenkin asiaan ja
tutustumaan Tritoniin.
{3Triton
Triton on kirjoitettu kirjastoksi, jota käytetään samalla tavalla kuin
käyttöjärjestelmän omiakin kirjastoja. Kirjasto avataan normaalisti, ja sen
jälkeen avataan Triton-projekti. Projekti käsittää ikkunan, jossa voi olla
valikoita ja sisältönä kaikenlaisia olioita. Ne kuvataan makrojen avulla
tavalla, joka tuo mieleen jonkinlaisen ohjelmoinnin opetuksessa käytetyn
pseudokielen. Tritonille kerrotaan, mitä halutaan mihinkin kohtaan, ja se
tekee oliot, laskee niille koon ja paikan jne. Tritonissa on "layout
engine", joka toimii kaikenkokoisilla kirjasimilla ja osaa laskea olioille
uuden koon ikkunan koon muuttuessa.
Kirjaston avaamiseen voit tutustua kurssin aiemmissa osissa. Tritonin
avaamisen jälkeen luodaan sovellus, mikä kuuluu alkutoimenpiteisiin. Tässä
on lyhyt koodi, joka tekee sen:
struct TR_App *App;
if(App=TR_CreateAppTags(
TRCA_Name, "MyApp",
TRCA_Release, "1.0",
TRCA_Version, "42.113",
TRCA_Date, "3.11.94",
TAG_END)) {
/* Avattu */
TR_DeleteApp(App);
} else {
/* Virhe */
}
Helpompi tapa kuitenkin on käyttää triton.lib-apukirjastossa olevia
TR_OpenTriton()- ja TR_CloseTriton()-funktioita, jotka tekevät molemmat, eli
TR_OpenTriton() avaa ensin kirjaston ja luo sitten sovelluksen. Sovellus on
struct Application, jossa Triton pitää kaikki ohjelmaasi koskevat tiedot.
Sovellukseen voidaan myöhemmin avata yksi tai useampia projekteja. Projekti
on nykyään sama kuin yksi Triton-ikkuna. Projektin määrittelyssä kuvataan
ensin ikkunan ominaisuudet, sitten valikot ja lopuksi ikkunan sisältö.
Esimerkki projektin avaamisesta:
struct TagItem dummyTags = {
TRWI_Title, (ULONG) "A dummy window",
TRWI_ID, 42,
TAG_END
};
void dummyFunction(void) {
struct TR_Project *dummyProject;
if(dummyProject=TR_OpenProject(Application,dummyTags)) {
/* Onnistui */
TR_CloseProject(dummyProject);
} else {
/* Virhe */
}
}
Projektilla tulee olla yksilöllinen tunniste (TRWI_ID). Sen pitää olla muu
kuin nolla, ja sen pitää pysyä samana. Triton tallentaa ikkunan koon ja muut
parametrit, joten ne hukkuvat, jos ID muuttuu joskus. Yllä olevassa koodissa
on staattinen taglista projektin kuvaamiseen. Triton ei tue
TAG_MORE-toimintoa, joten listoja ei voi yhdistellä. Joskus voi olla tarpeen
käyttää TR_OpenProjectTags()-kutsua sen sijaan, jolloin taglista rakennetaan
dynaamisesti ja ajoaikaisesti pinoon. Tämä tietysti kuluttaa paljon
pinomuistia sekä pidentää ja hidastaa ohjelmaa, joten kovin pitkiä
taglistoja ei kannata näin rakennella.
Yllä olevissa koodeissa käytetään tagien nimiä, mutta paljon selkeämpi
tapakin taglistojen tekemiseen on olemassa: makrot. Niillä voidaan kuvata
melkein kaikki tarpeellinen. Esimerkiksi ikkuna kuvataan näin:
WindowTitle("A dummy window"),
WindowID(42),
EndProject
Myös olioille ja valikkovalinnoille on olemassa makrot. Tarkemmin
määrittelyjen tekeminen ja makrojen käyttäminen siinä selviää artikkelin
lopussa olevasta ohjelmaesimerkistä.
{2Oliot
Tritonin toiminta perustuu olioihin ja ohjelman käyttäjän kanssa käymä
kommunikaation niiltä saataviin viesteihin. Tässä on aluksi luettelo
kaikista Triton-olioista:
Button BOOPSI button gadget
CheckBox GadTools CheckBox
Cycle GadTools Cycle and MX gadget
DropBox AppIcon dropping box
FrameBox Framing or grouping box
Group Triton's layout engine
Image Image
Line 3D line
Listview GadTools Listview
Palette GadTools Palette gadget
Progress Progress indicator
Scroller GadTools Scroller
Slider GadTools Slider
Space Empty space
String GadTools String gadget
Text Text
Taulukko 1. Triton-oliot.
Näistä muutamat ovat yksinkertaisia: Text näyttää tekstiä, Line tekee viivan
ja niin edelleen. Sitten on todella monimutkaisia ja kehittyneitä olioita
kuten palettigadget, Listview-gadget ja Progress indicator eli valmiiksi
rakennettu edistysosoitin, jossa on tiettyyn suuntaan työn etenemisen mukaan
virtaava palkki, joten käyttäjä näkee, missä vaiheessa työ on. Group-olio
liittyy Tritonin layout engineen. Sen avulla voidaan ohjata olioiden
sijoittelua ikkunaan. Niitä voidaan ryhmitellä pysty- ja vaakasuunnassa,
keskittää ja jaotella eri tavoin. Tässä jutussa en käy olioita läpi
yksityiskohtaisesti, mutta lopun lähdekoodissa on hieman asiaa niistä.
Asiaan voidaan palata jatkossa.
Olioilla on attribuutteja, joiden arvo voidaan lukea funktiolla
TR_GetAttribute(). Niitä voidaan myös asettaa funktiolla TR_SetAttribute().
Joidenkin olioiden kaikkia attribuutteja ei voida muuttaa jälkikäteen, vaan
arvot ovat pysyviä, kun ne luomishetkellä on määritelty. Tällaisia
muuttamattomia attribuutteja on esimerkiksi Listview-gadgetin entrylista.
{2Viestit
Tritonilta saadaan monenlaisia viestejä. Se voi kertoa ikkunan sulkunappulan
painamisesta tai sisäisestä virheestä. Tärkeimmät viestit ovat NEWVALUE ja
ACTION. Ne ovat olioiden lähettämiä viestejä ja kertovat, että käyttäjä on
tehnyt niille jotakin. Nappulaa voi olla painettu tai vieritintä vieritetty.
Viestiin sisältyy tarkka tieto siitä, mitä on tapahtunut. Triton-ohjelman
toiminta perustuu viestien vastaanottamiseen ja niiden tulkintaan. Yksi
lähdekoodi kertoo enemmän kuin kaksituhatta tavua, joten tämäkin selviää
parhaiten esimerkkikoodista.
Myös oliot keskustelevat Tritonin kanssa viesteillä. Näiden viestien kanssa
sovellus ei kuitenkaan ole yleensä tekemisissä. Sen sijaan esimerkiksi
TR_SetAttribute()-funktion kutsuminen saa Tritonin lähettämään kohdeoliolle
asianmukaisen viestin. Olioille voi kyllä lähettää suoraankin viestejä,
mutta se ei ole yleensä tarpeen. Kaikki kanssakäyminen niiden kanssa voidaan
toteuttaa helposti Tritonin kautta.
{2Help
Tritonissa on kaksi apua-toimintoa. QuickHelp-toiminto ollessaan päällä
näyttää ruudulla pieniä aputekstejä, kun hiiren osoitin on sellaisen olion
päällä, jolle on sellainen määritelty. Monet oliot eivät kuitenkaan tue tätä
toimintoa vielä. Ohjelmaesimerkissä QuickHelp on päällä oletuksena ja sen
tilaa voi muuttaa valikosta. Ylemmässä nappulassa on määriteltynä pieni
aputeksti. Alempaan cycle-gadgetiin ei sellaista saa, koska kyseinen olio
kuuluu niihin, jotka eivät peri attribuutteja yläluokilta. QuickHelp kun on
abstraktin DisplayObject-luokan attribuutti eikä GUI-olioiden itsensä.
Toinen tapa on manuaalinen helppi. Jos projektimäärittelyssä on TWRF_HELP
päällä, Triton lähettää TRMS_HELP-viestin joka kerta, kun käyttäjä painaa
Help-näppäintä. Sen jälkeen on sinun vastuullasi näyttää käyttäjälle hänen
haluamaansa apua. Tavallisinta on avata ohjelman AmigaGuide-dokumentti siitä
kohtaa, jossa käsitellään sitä asiaa. Viestin ID-kentässä on sen olion
tunniste, josta käyttäjä haluaa tietoa.
{2Loppusanat
Tarkempaa tietoa Triton-ohjelmoinnista saat
Developer/TritonDev.guide-dokumentista ja Tritonin includetiedostosta sekä
autodoceista. Niissä on selitetty kaikki kirjastoon liittyvät asiat. Tämän
artikkelin ei missään nimessä ollutkaan tarkoitus olla tyhjentävä selvitys
Triton-ohjelmoinnista. Siihen ei millään olisi aikaa eikä tilaa. Monia
kysymyksiä jää auki ja monet asiat ehkäpä sekaviksi, mutta lukemalla
Tritonin ohjeita ne selviävät. Tarkoitukseni olikin lähinnä tarjota helppo
johdanto tähän kiehtovaan GUI-maailmaan, jonka tarjoaa Triton!
{3Ohjelmakoodia
Tässä on kätevä ohjelmarunko, josta voi todella nopeasti tehdä pienen
ohjelman. Siinä on kaikki tarvittava AmigaDOS-standardisen ohjelman
tekemiseksi. Se käsittelee argumentit, sisältää cleanup-koodin sekä
tarvittavan koodin virheilmoituksen näyttämiseen. Korvaa alussa kommentissa
ja versiomerkkijonossa oleva "`"-merkki ohjelman nimellä (kätevästi esim.
Edissä "2e/`/Ohjelma"), laita ohjelman argumenttikuvaus
template-merkkijonoon ja ala kirjoittaa koodia! Puitteet ovat valmiit.
Koodi käyttää _main()-entrypointtia, kuten yleensäkin, koska sillä päästään
eroon monesta kilosta turhaa koodia, esimerkiksi C-kääntäjän argumenttien
parseamisesta, joka on AmigaDOS-ympäristössä tarpeetonta. Koodi käyttää sen
tekemiseen DOS-funktiota ReadArgs(), johon tutustumme lähemmin kurssin
tulevissa osissa. ReadArgs() käsittelee argumentit standardilla tavalla, ja
se myös varmistaa, että saat tarvitsemasi argumentit. Jos niitä ei ole
annettu, koodi tulostaa virheilmoituksen ja palauttaa sinut shelliin.
Käytettävissäsi on myös ohjelman nimi cmd-puskurissa. Sitä käytetään
virheilmoitusten näyttämiseen, ja koodi kysyy sen ensi töikseen DOSilta.
Argumentit ovat args-taulukossa, ensimmäisessä alkiossa ensimmäinen jne.
Mikäli argumentti on merkkijono, alkiossa on osoitin siihen. Jos se on
numeraalinen, alkio on nolla, jos sitä ei ole annettu (mikäli sen voi jättää
antamatta), tai OSOITIN longwordiin, jossa on argumentin arvo. Argumentit
kuvataan nk. templatella, jonka AmigaDOS-ohjelmat kertovat antamalla
ainoaksi argumentiksi kysymysmerkin.
Template voi olla esimerkiksi "FILE/A,LENGTH/N". Tällöin FILE on ensimmäinen
argumentti ja merkkijono. LENGTH on toinen ja numeraalinen. Argumentin nimen
perässä tulevat kirjaimet kertovat sen tyypin. A tarkoittaa pakollista
argumenttia. Jos se puuttuu, ohjelma ei lähde käyntiin. N tarkoittaa
numeraalista argumenttia. LENGTH-argumentissa ei ole A-määrittelyä, joten se
ei ole pakollinen. Jos sitä ei anneta, args[1] on nolla. Määrittelyjä voi
yhdistää, ja esimerkiksi pakollinen numeraaliargumentti olisi "/N/A". Kaikki
määrittelyt on selitetty Using The System Software -kirjassa sivulla 8-5
(sekä enemmän ohjelmoijan näkökulmasta dos.libraryn autodoceissa
ReadArgs()-funktion yhteydessä). Kerron niistä vielä lisää kurssin DOSia
käsittelevässä osassa.
/* `.c */
#include "exec/io.h"
#include "exec/memory.h"
#include "exec/libraries.h"
#include "exec/execbase.h"
#include "dos/dos.h"
#include "proto/exec_protos.h"
#include "proto/dos_protos.h"
#define TRUE 1
#define FALSE 0
typedef unsigned char u_char
int _main(void);
void error(u_char *),cleanup(void);
struct RDArds *ra;
ULONG args[2];
u_char template[]="",ver[]="$VER: ` 1.00",cmd[32];
int _main(void) {
LONG i;
GetProgramName(cmd,32);
if(!(ra=ReadArgs((STRPTR)template,args,NULL))) {
PrintFault(i=IoErr(),cmd);
exit(i);
}
/* Tähän koodi. */
cleanup();
return(RETURN_OK);
};
void error(u_char *str) {
printf("%s: %s\n",cmd,str);
cleanup();
exit(RETURN_FAIL);
};
void cleanup(void) {
if(ra) FreeArgs(ra);
};
{2Toimiva GUI-ohjelma
Nyt tulee kurssin ensimmäinen täydellinen lähdekoodi, joka kääntyy täydeksi
ohjelmaksi. Mitään se ei kyllä tee, mutta se rakentaa yksinkertaisen
graafisen käyttöliittymän, ja koodista voi kommentoinnin myötävaikutuksella
oppia paljon Tritonin käyttämisestä. Lähdekoodin osia tai koko koodiakin saa
käyttää omissa ohjelmissaan. Maininta sen alkuperästä on kyllä suotavaa.
Voit joutua muuttamaan koodista pieniä osia kuten
prototyyppimäärittelytiedostojen nimiä tai muiden include-tiedostojen
hakemistoja tai muuta sellaista saadaksesi sen kääntymään. Koodi kuitenkin
kääntynee sellaisenaan. Itse käänsin sen DICE:llä ja GCC:llä.
Koodi on alun perin kirjoitettu edellä nähdyn yleispohjan päälle. Nyt tästä
koodista saa rungon GUI-ohjelmalle. Projektimäärittelyjä ja pääsilmukan
toimintoja muuttamalla voi helposti tehdä ohjelman, jossa on hieno graafinen
käyttöliittymä. Jos haluat koodista dokumentoimattoman version, jota ei ole
myöskään pilkottu useammille riveille, saat sen minulta pyytämällä. Avustan
myös boksissani henkilökohtaisesti ohjelmointiteknisissä ongelmatilanteissa.
/* TritonCode.c */
/* Tämä lähdekoodi on pohja mille tahansa ohjelmalle, jossa on graafinen
käyttöliittymä. Koodista voi helposti rakennella valmiin ohjelman. */
#include "exec/io.h"
#include "exec/memory.h"
#include "exec/libraries.h"
#include "exec/execbase.h"
#include "dos/dos.h"
#include "libraries/triton.h"
#include "proto/exec_protos.h"
#include "proto/dos_protos.h"
#include "proto/triton_protos.h"
#define TRUE 1
#define FALSE 0
typedef unsigned char u_char
/* Tämä on oma Triton-oliomäärittelymakroni. Se on CenteredButton, johon
on ujutettu mukaan help-stringi. Alun perin se on ollut yhdellä rivillä,
ja se kannattaa siihen muotoon palauttaa. Silloin voi ottaa pois rivien
lopuissa olevat kenoviivat, jotka saavat kääntäjän jättämään seuraavan
rivinvaihdon huomiotta, mikä on tarpeen, koska makromäärittelyn pitää
olla samalla rivillä. Näinkin se toimii, mutta hyvältä se ei näytä. */
#define CenteredButtonHelp(t,i,str) HorizGroupSC,Space,TROB_Button,0L,\
TRAT_Text,(ULONG)(t),TRAT_ID,(i),TRDO_QuickHelpString,((ULONG)(str)),\
Space,EndGroup
int _main(void);
void DoStuff(void),error(u_char *),cleanup(void);
struct RDArds *ra;
struct TR_Project *project; /* Osoitin Triton-projektiin */
struct TR_Message *trmsg; /* Vastaanotettu viesti */
ULONG args[2];
/* Yleisiä merkkijonoja, versio, virheilmoitukset jne. Ohjelman nimi
on s_prg:ssä, jota käytetään ohjelmassa aina, kun sitä tarvitaan. */
u_char template[]="",ver[]="$VER: TritonCode 1.00",cmd[32],
err_gui[]="unable to create GUI",s_prg[]="TritonCode";
/* Kiertonappulan vaihtoehdot. Nämä merkkijonot kiertävät nappulassa
aina kun sitä painetaan. */
u_char *CycleEntries[] = {
"Poutaa","Pilvistä","Sadetta","Myrskyä",0
};
/* Nämä ovat ohjelmassa käytettävien Triton-olioiden tunnistenumerot.
Ensimmäiset kolme ovat valikkovalintoja ja loput ikkunassa olevia
nappuloita. Pidän ne eri kymmenluvuilla selvyyden vuoksi. */
#define ID_About 1
#define ID_Help 2
#define ID_Quit 3
#define ID_Ask 10
#define ID_Cycle 11
/* Tämä on Triton-projektin määrittely. Se kuvaa projektin käyttämän
ikkunan, valikot ja ikkunan sisällön eli nappulat ja muut jutut. */
ProjectDefinition(prod) {
WindowID(1),
WindowPosition(TRWP_CENTERSCREEN),
WindowTitle("TritonCode 1.00"),
BeginMenu("Project"), /* Valikko */
MenuItem("A_About",ID_About), /* Ensimmäinen valinta */
MenuItemCC("H_Autohelp",ID_Help), /* CheckMark-valinta */
ItemBarlabel, /* Välirivi */
MenuItem("Q_Quit",ID_Quit), /* Hotkey rcommand-Q */
/* Ikkunan sisältö. Pitää alkaa ryhmäoliolla. */
VertGroupA,
SpaceB, /* Iso väli */
/* Keskitetty nappula, johon kuuluu aputeksti */
CenteredButtonHelp("Kysymys",ID_Ask,
"Vastaa hassuun kysymykseen"),
SpaceB,HorizSeparator,SpaceB, /* Välit ja vaakaviiva */
/* Vaakasuuntainen ryhmä, jossa on ensin teksti vasemmalla ja
sitten cycle-gadget oikealla. Cycle-gadget on tehty makron
sijaan suoraan tageja käyttämällä. */
HorizGroupEAC,SpaceB,
TextN("Säätila"),SpaceB,TROB_Cycle,(ULONG)CycleEntries,
TRAT_ID,ID_Cycle,TRAT_Value,0,
SpaceB,EndGroup,
SpaceB,
EndGroup,
EndProject
};
/* Tämä määrittely kuvaa About-valitsimen. BeginRequester() määrittelee
valitsimen otsikon ja sijainnin, tässä se tulee ruudun otsikkorivin
alle. Valitsin koostuu viidestä rivistä tekstiä sekä yhdestä eroke-
viivasta eli "horisontaalisesta separaattorista". Lopuksi määritellään
valitsimen nappulat, joita on tässä vain yksi, jonka ainoa tarkoitus
on sulkea valitsin. Mitään tietoa tämä valitsin ei käyttäjältä
ohjelmalle välitä. Nappula on keskitetty, ja siihen voi vastata myös
Returnilla (R) ja Escapella (E). Myös "O" käy. Nappulan nimessä oleva
alaviiva tekee sitä seuraavasta kirjaimesta nappulan hotkeyn. */
ProjectDefinition(abouttags) {
BeginRequester("About...",TRWP_BELOWTITLEBAR),
VertGroupA, Space, CenteredText3("TritonCode 1.00"),
SpaceS, CenteredText("©1996 by Sami Klemola"),
Space, HorizSeparator,
Space, CenteredText("This program is using the"),
SpaceS, CenteredText("Triton GUI creation system"),
SpaceS, CenteredText("which is © by Stefan Zeiger"),
Space, EndGroup,
BeginRequesterGads,
CenteredButtonRE("_Ok",1),
EndRequester
};
/* Toinen valitsin pomppaa ruudulle, tällä kertaa keskelle sitä, kun
painetaan Kysymys-nappulaa. Tähän valitsimeen voi vastata kahdella
tavalla, joten meillä on kaksi nappulaa. Se vaatii hieman enemmän työtä
kuin yhden nappulan laittaminen. Niihinkin voi vastata hotkeyllä. Tämän
valitsimen näytettyään funktio palauttaa sen nappulan tunnisteen, joka
valittiin. Valitsimen tunnisteet eivät ole samaa sarjaa ikkunassa
olevien kanssa, joten tässä ne ovat yksi ja nolla. */
ProjectDefinition(asktags) {
BeginRequester("Kysymys",TRWP_CENTERSCREEN),
VertGroupA, Space,
CenteredText("Jotkut ihmiset ovat sitä mieltä, että"),
SpaceS,
CenteredText("heidän päänsä ympärillä on jotakin."),
SpaceS,
CenteredText("Tuntuuko sinusta, että vanne puristaa päätäsi?"),
Space, EndGroup,
BeginRequesterGads,
LineArray,BeginLine,
Space,
CenteredButtonR("_Kyllä",1),
Space,
CenteredButtonE("_Ei kai",0),
Space,
EndLine,EndArray,
EndRequester
};
/* Pääohjelma avaa Tritonin ja Triton-projektin sekä asettaa pika-avun
päälle heti. TR_OpenTriton()-funktiolle annetaan tiedot ohjelmasta.
Niitä voi katsella Tritonin Prefs-editorilla. */
int _main(void) {
LONG i;
GetProgramName(cmd,32);
if(!(ra=ReadArgs((STRPTR)template,args,NULL))) {
PrintFault(i=IoErr(),cmd);
exit(i);
}
if(!(TR_OpenTriton(TRITON11VERSION,
TRCA_Name,s_prg,TRCA_LongName,s_prg, /* Ohjelman nimi */
TRCA_Info,(ULONG)"GUI Demo", /* Ohjelman kuvaus */
TRCA_Version,(ULONG)"1.00", /* Versionumero */
TRCA_Release,(ULONG)"1", /* Julkaisu */
TRCA_Date,(ULONG)"1-Mar-96",TAG_END))) /* Päiväys */
error("triton.library needed");
if(!(project=TR_OpenProject((struct TR_App *)Application,prod)))
error(err_gui);
TR_SetAttribute(project,0,TRWI_QuickHelp,TRUE);
DoStuff();
cleanup();
return(RETURN_OK);
};
/* DoStuff() on pääsilmukka, joka perustuu Tritonin lähettämien viestien
vastaanottamiseen ja tulkintaan sekä niiden pohjalta toimimiseen. */
void DoStuff(void) {
while(TRUE) {
while(trmsg=(struct TR_Message *)TR_GetMsg(Application)) {
/* Saapuneet viestit käsitellään luokkakohtaisesti. */
switch(trmsg->trm_Class) {
/* Ikkunan sulkunappulaa on painettu. Vastataan kaikkiin viesteihin ja
poistutaan. Triton tosin vapauttaa itsekin viesteille varatun muistin,
mutta ei välttämättä viesteihin liittyviä resursseja, joten tällainen
ReplyMsg()-silmukka on hyvä olla. */
case TRMS_CLOSEWINDOW:
TR_ReplyMsg(trmsg);
while(trmsg=(struct TR_Message *)
TR_GetMsg(Application)) TR_ReplyMsg(trmsg);
return();
/* Tritonissa on sattunut virhe. Lienee harvinaista. Periaatteessa ilmoitus
pitäisi näyttää valitsimessa, mutta tulostaminen stdoutiinkin
käynee, koska tätä ei pitäisi tapahtuakaan. */
case TRMS_ERROR:
printf("%s: %s\n",cmd,
TR_GetErrorString(trmsg->trm_Data));
break;
/* NEWVALUE-viestit kertovat olion tilan muuttumisesta. Tällaisen viestin
lähettävät esimerkiksi TOGGLE-tyyppiset (CHECKMARK) valikkovalinnat,
kuten tässä ohjelmassa Autohelp, sekä Listview- ja Cycle-gadgetit. Olion
uusi arvo on viestin datakentässä. */
case TRMS_NEWVALUE:
switch(trmsg->trm_ID) {
case ID_Help:
TR_SetAttribute(project,0,TRWI_QuickHelp,
trmsg->trm_Data);
break;
/* Tässä kohtaa pitäisi tietysti olla "case ID_Cycle:",
jossa käsiteltäisiin säätilan vaihtuminen. Toinen
mahdollisuus on toki se, että jos kyseessä on
sellainen valinta, että sitä tarvitaan vasta
tietyssä vaiheessa, ei tällaista tarvita, vaan
tietoa tarvittaessa käytetään TR_GetAttribute()-
funktiota olion tilan selvittämiseen. Tähän
esimerkkiin en kumpaakaan ole laittanut tilaa
viemään ja sekoittamaan ihmisiä. */
}
break;
/* ACTION-viestin synnyttää esimerkiksi tavallinen nappula, tässä ohjelmassa
Kysymys-gadget, sekä tavallinen menuvalinta, jolla käynnistetään jokin
toiminto. Alla käsitellään kaikki tämän ohjelman kolme ACTION-tyyppisiä
viestejä heittelevää oliota. Olioiden kuvaavat tunnistenumerot ovat avuksi
toimintojen selvittämiseksi koodista. About-menuvalinnasta aukeaa
tavalliseen tapaan pieni valitsin, joka näyttää ohjelmasta tietoja.
Valitsin on suoraan kopioitu Tritonin demokoodista, mutta tekstejä on
tietysti hieman vaihdettu. Quit-valinta aikaansaa saman kuin ikkunan
sulkunappulan painaminen, eli vastataan kaikkiin viesteihin ja poistutaan.
Oikeassa ohjelmassa tässä pitäisi olla vielä valitsin, joka kysyisi,
haluaako käyttäjä varmasti poistua ja antaisi hänelle vielä Cancel-option.
Ask-nappulan toteutus on samantapainen kuin About-valikkovalinnan. Se
näyttää valitsimen, ja oikea koodi tietysti katsoisi funktion palauttaman
arvon, koska se sisältää tiedon siitä, mitä nappulaa käyttäjä painoi
valitsimen sulkemiseksi. */
case TRMS_ACTION:
switch(trmsg->trm_ID) {
case ID_About:
TR_AutoRequest(Application,project,abouttags);
break;
case ID_Quit:
TR_ReplyMsg(trmsg);
while(trmsg=(struct TR_Message *)
TR_GetMsg(Application)) TR_ReplyMsg(trmsg);
return();
case ID_Ask:
TR_AutoRequest(Application,project,asktags);
break;
}
break;
}
/* Kun viesti on käsitelty, tai ohitettu, jos se ei ollut haluttua tyyppiä,
vaan esimerkiksi TRMS_KEYPRESSED, joka kertoo näppäimen painamisesta ja
joita tässä ohjelmassa ei käsitellä, siihen vastataan, ja sen jälkeen
jäädään odottamaan uutta viestiä. */
TR_ReplyMsg(trmsg);
}
TR_Wait(Application,0);
}
};
/* Tämä funktio tulostaa virheilmoituksen tavanomaiseen AmigaDOS-tapaan,
eli formaatti on "ohjelma: virhe". Funktio käyttää _main()-funktion
alussa DOSilta kysymäänsä nimeä. */
void error(u_char *str) {
printf("%s: %s\n",cmd,str);
cleanup();
exit(RETURN_FAIL);
};
/* Tätä funktiota kutsutaan aina ohjelmasta poistuttaessa. Tässä ohjelmassa
ei ole paljon siivottavaa, joten funktio sulkee vain Triton-projektin ja
sitten Tritonin itsensä. Lopuksi vapautetaan argumentit, joita tässä
ohjelmassa ei tosin käytetäkään. */
void cleanup(void) {
if(project) TR_CloseProject(project);
TR_CloseTriton();
if(ra) FreeArgs(ra);
};
{3Mitä seuraavaksi?
Jatkoa seuraa ensi numerossa. En ole vielä päättänyt, mikä seuraavan osan
aihe on, mutta se selviää todennäköisesti viimeistään silloin, kun se on
valmis. Todennäköisesti on aika alkaa käsitellä DOS-kirjastoa, koska se
tarjoaa paljon kaikkien ohjelmien tarvitsemia palveluita. Samalla tai ehkä
jatkossa pitää myös paneutua enemmän aikaisemmissa osissa liian nopeasti
käsiteltyihin asioihin. Lähdekoodia on luvassa myös jatkossa. Palautettakin
otetaan vastaan.